package com.jay.media.music.core.provider

import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Bitmap
import android.media.MediaMetadata
import android.os.Build
import android.provider.MediaStore
import android.text.TextUtils
import android.util.Log
import com.jay.media.kit.MD5Utils
import com.jay.media.music.core.util.AlbumUtils
import java.io.File
import java.io.FileOutputStream

/**
 * Create by xuzhou4
 * Date 2021/11/8
 */

private const val TAG = "LocalMusicSource"

class LocalMusicSource(
    var mContext: Context
) : MusicProviderSource {

    private var imgDitFile: File? = null

    @SuppressLint("WrongConstant")
    override fun iterator(): Iterator<MediaMetadata> {
        Log.d(TAG, "iterator")
        imgDitFile = mContext.getExternalFilesDir("img")
        if (imgDitFile?.exists() == false) {
            imgDitFile?.mkdirs()
        }

        val startTime = System.currentTimeMillis()
        val musicList = ArrayList<MediaMetadata>()
        val columns = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            arrayOf(
                MediaStore.Audio.Media._ID,
                MediaStore.Audio.Media.DATA,
                MediaStore.Audio.Media.DISPLAY_NAME,
                MediaStore.Audio.Media.DURATION,
                MediaStore.Audio.Media.MIME_TYPE,
                MediaStore.Audio.Media.ARTIST,
                MediaStore.Audio.Media.ARTIST_ID,
                MediaStore.Audio.Media.ALBUM,
                MediaStore.Audio.Media.ALBUM_ID,
                MediaStore.Audio.Media.GENRE,
                MediaStore.Audio.Media.TITLE
            )
        } else {
            arrayOf(
                MediaStore.Audio.Media._ID,
                MediaStore.Audio.Media.DATA,
                MediaStore.Audio.Media.DISPLAY_NAME,
                MediaStore.Audio.Media.DURATION,
                MediaStore.Audio.Media.MIME_TYPE,
                MediaStore.Audio.Media.ARTIST,
                MediaStore.Audio.Media.ARTIST_ID,
                MediaStore.Audio.Media.ALBUM,
                MediaStore.Audio.Media.ALBUM_ID,
                MediaStore.Audio.Media.TITLE
            )
        }

        val cursor = mContext.contentResolver.query(
            MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
            columns,
            null,
            null,
            null,
            null
        )

        try {
            if (cursor != null) {
                val idIndex = cursor.getColumnIndex(MediaStore.Audio.Media._ID)
                val displayNameIndex = cursor.getColumnIndex(MediaStore.Audio.Media.DISPLAY_NAME)
                val durationIndex = cursor.getColumnIndex(MediaStore.Audio.Media.DURATION)
                val mimeTypeIndex = cursor.getColumnIndex(MediaStore.Audio.Media.MIME_TYPE)
                val dataIndex = cursor.getColumnIndex(MediaStore.Audio.Media.DATA)
                val artistIndex = cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST)
                val artistIDIndex = cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST_ID)
                val albumIndex = cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM)
                val albumIDIndex = cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID)
                val titleIndex = cursor.getColumnIndex(MediaStore.Audio.Media.TITLE)
                val genreIndex = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
                    cursor.getColumnIndex(MediaStore.Audio.Media.GENRE)
                } else {
                    -1
                }
                Log.d(TAG, "genreIndex $genreIndex")

                while (cursor.moveToNext()) {
                    val id = cursor.getLong(idIndex)
                    val displayName = cursor.getString(displayNameIndex)
                    val duration = cursor.getLong(durationIndex)
                    val mimeType = cursor.getString(mimeTypeIndex)
                    val data = cursor.getString(dataIndex)
                    val artist = cursor.getString(artistIndex)
                    val artistID = cursor.getString(artistIDIndex)
                    val album = cursor.getString(albumIndex)
                    val albumID = cursor.getLong(albumIDIndex)
                    val title = cursor.getString(titleIndex)

                    val mediaMetaDataBuilder = MediaMetadata.Builder()
                        .putString(MediaMetadata.METADATA_KEY_MEDIA_ID, id.toString())
                        .putString(METADATA_TRACK_SOURCE, data)
                        .putString(MediaMetadata.METADATA_KEY_MEDIA_URI, data)
                        .putString(MediaMetadata.METADATA_KEY_DISPLAY_TITLE, title)
                        .putString(MediaMetadata.METADATA_KEY_TITLE, title)
                        .putLong(MediaMetadata.METADATA_KEY_DURATION, duration)
                        .putString(MediaMetadata.METADATA_KEY_ALBUM, album)
                        .putString(MediaMetadata.METADATA_KEY_ARTIST, artist)

                    val toLowerCaseString = MD5Utils.toLowerCaseString(data)
                    Log.d(TAG, "path -> $data")
                    Log.d(TAG, "md5 -> $toLowerCaseString")

                    val albumArt = File(
                        imgDitFile,
                        "$toLowerCaseString.png"
                    )
                    if (!albumArt.exists()) {
                        val artwork = AlbumUtils.getArtwork(mContext, id, albumID, false)
                        Log.d(TAG, "artwork $artwork")

                        artwork?.also {
                            val fos = FileOutputStream(albumArt)
                            it.compress(Bitmap.CompressFormat.PNG, 100, fos)
                            fos.close()

                            mediaMetaDataBuilder.putString(
                                MediaMetadata.METADATA_KEY_ALBUM_ART_URI,
                                albumArt.absolutePath
                            )
                        }
                    } else {
                        mediaMetaDataBuilder.putString(
                            MediaMetadata.METADATA_KEY_ALBUM_ART_URI,
                            albumArt.absolutePath
                        )
                    }

                    if (genreIndex >= 0) {
                        val genre = cursor.getString(genreIndex)
                        if (!TextUtils.isEmpty(genre)) {
                            mediaMetaDataBuilder.putString(MediaMetadata.METADATA_KEY_GENRE, genre)
                        }
                    }

                    val mediaMetaData = mediaMetaDataBuilder.build()
                    musicList.add(
                        mediaMetaData
                    )
                }
            }
        } catch (e: Exception) {
            Log.d(TAG, "iterator process exception : ${e.message}")
        } finally {
            cursor?.close()
        }
        Log.d(
            TAG,
            "iterator complete, count -> ${musicList.size} spendTime -> ${System.currentTimeMillis() - startTime}"
        )
        return musicList.iterator()
    }
}